package cn.ug.product.service.impl;

import cn.ug.aop.RemoveCache;
import cn.ug.aop.SaveCache;
import cn.ug.bean.base.DataTable;
import cn.ug.config.Config;
import cn.ug.core.ensure.Ensure;
import cn.ug.product.bean.GoldLatestPriceBean;
import cn.ug.product.bean.GoldPriceRecordBean;
import cn.ug.product.bean.GoldPriceTrendBean;
import cn.ug.product.mapper.GoldPriceRecordMapper;
import cn.ug.product.mapper.entity.GoldPriceRecord;
import cn.ug.product.service.GoldPriceRecordService;
import cn.ug.service.impl.BaseServiceImpl;
import cn.ug.util.BigDecimalUtil;
import cn.ug.util.UF;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.commons.lang3.StringUtils;
import org.dozer.DozerBeanMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;

import static cn.ug.config.CacheType.OBJECT;
import static cn.ug.config.CacheType.SEARCH;

/**
 * @author kaiwotech
 */
@Service
public class GoldPriceRecordServiceImpl extends BaseServiceImpl implements GoldPriceRecordService {

    @Resource
    private GoldPriceRecordMapper goldPriceRecordMapper;

    @Resource
    private DozerBeanMapper dozerBeanMapper;

    static final int YEAR = 365;
    static final int MONTH = 30;
    static final int week = 7;

    @Resource
    private Config config;

    @Autowired
    public List<GoldPriceRecordBean> queryLatestRecordThree() {
        List<GoldPriceRecord> list = goldPriceRecordMapper.queryLatestRecordThree();
        List<GoldPriceRecordBean> dataList = new ArrayList<>();
        for (GoldPriceRecord o : list) {
            GoldPriceRecordBean objBean = dozerBeanMapper.map(o, GoldPriceRecordBean.class);
            objBean.setTimeString(UF.getFormatDateTime(o.getTime()));
            objBean.setAddTimeString(UF.getFormatDateTime(o.getAddTime()));
            objBean.setModifyTimeString(UF.getFormatDateTime(o.getModifyTime()));
            dataList.add(objBean);
        }
        return dataList;
    }

    @Override
    public List<GoldLatestPriceBean> listLatestValue(String startDate, String endDate) {
        if (StringUtils.isNotBlank(startDate) && StringUtils.isNotBlank(endDate)) {
            List<GoldLatestPriceBean> priceBeans = goldPriceRecordMapper.listLatestValue(startDate, endDate);
            if (priceBeans != null && priceBeans.size() > 0) {
                List<GoldLatestPriceBean> beans = goldPriceRecordMapper.listOpeningAndClosingPrice(startDate, endDate);
                if (beans != null && beans.size() > 0) {
                    for (GoldLatestPriceBean priceBean : priceBeans) {
                        for (GoldLatestPriceBean bean : beans) {
                            if (StringUtils.equals(bean.getTime(), priceBean.getTime())) {
                                priceBean.setOpeningPrice(bean.getOpeningPrice());
                                priceBean.setClosingPrice(bean.getClosingPrice());
                                break;
                            }
                        }
                    }
                }
                for (GoldLatestPriceBean priceBean : priceBeans) {
                    if (priceBean.getClosingPrice() == null) {
                        priceBean.setClosingPrice(priceBean.getLatestpri());
                    }
                    if (priceBean.getOpeningPrice() == null) {
                        priceBean.setOpeningPrice(priceBean.getLatestpri());
                    }
                }
            }
            return priceBeans;
        }
        return null;
    }

    @Override
    @RemoveCache(cleanSearch = true)
    @Transactional(rollbackFor = Exception.class)
    public int save(GoldPriceRecordBean entityBean) {
        // 数据完整性校验
        if (null == entityBean || StringUtils.isBlank(entityBean.getVariety()) || BigDecimalUtil.isZeroOrNull(entityBean.getLatestpri())) {
            Ensure.that(true).isTrue("00000002");
        }
        GoldPriceRecord entity = dozerBeanMapper.map(entityBean, GoldPriceRecord.class);
        if (StringUtils.isBlank(entity.getId())) {
            entity.setId(UF.getRandomUUID());
        }
        if (StringUtils.isNotBlank(entityBean.getTimeString())) {
            entity.setTime(UF.getDateTime(entityBean.getTimeString()));
        }
        int rows = goldPriceRecordMapper.insert(entity);
        Ensure.that(rows).isLt(1, "00000005");
        return 0;
    }

    @Override
    @RemoveCache(cleanSearch = true, cleanObjectByKeyPosition = 0)
    public int delete(String id) {
        if (StringUtils.isBlank(id)) {
            return 0;
        }

        return goldPriceRecordMapper.delete(id);
    }

    @Override
    @RemoveCache(cleanSearch = true, cleanObjectByKeyPosition = 0)
    public int deleteByIds(String[] id) {
        if (id == null || id.length <= 0) {
            return 0;
        }

        return goldPriceRecordMapper.deleteByIds(id);
    }

    @Override
    @SaveCache(cacheType = OBJECT)
    public GoldPriceRecordBean findById(String id) {
        if (StringUtils.isBlank(id)) {
            return null;
        }

        GoldPriceRecord entity = goldPriceRecordMapper.findById(id);
        if (null == entity) {
            return null;
        }

        GoldPriceRecordBean entityBean = dozerBeanMapper.map(entity, GoldPriceRecordBean.class);
        entityBean.setTimeString(UF.getFormatDateTime(entity.getTime()));
        entityBean.setAddTimeString(UF.getFormatDateTime(entity.getAddTime()));
        entityBean.setModifyTimeString(UF.getFormatDateTime(entity.getModifyTime()));
        return entityBean;
    }

    @Override
    public GoldPriceRecordBean findLastByTime() {
        GoldPriceRecord o = goldPriceRecordMapper.queryLatestRecord();
        if (o != null) {
            GoldPriceRecordBean objBean = dozerBeanMapper.map(o, GoldPriceRecordBean.class);
            objBean.setTimeString(UF.getFormatDateTime(o.getTime()));
            objBean.setAddTimeString(UF.getFormatDateTime(o.getAddTime()));
            objBean.setModifyTimeString(UF.getFormatDateTime(o.getModifyTime()));
            return objBean;

        }
        return null;
    }

    @Override
    public double selectSomedayPrice(String searchTime) {
        Double price = goldPriceRecordMapper.selectSomedayPrice(searchTime);
        if (price == null) {
            GoldPriceRecord o = goldPriceRecordMapper.queryLatestRecord();
            if (o != null) {
                price = o.getLatestpri().doubleValue();
            } else {
                price = 0.0;
            }
        }
        return price;
    }

    @Override
    @SaveCache(cacheType = SEARCH)
    public DataTable<GoldPriceRecordBean> query(String order, String sort, int pageNum, int pageSize, Integer type,
                                                LocalDateTime addTimeMin, LocalDateTime addTimeMax, String keyword) {
        Page<GoldPriceRecordBean> page = PageHelper.startPage(pageNum, pageSize);
        List<GoldPriceRecordBean> list = queryDetail(order, sort, type, addTimeMin, addTimeMax, keyword);
        return new DataTable<>(page.getPageNum(), page.getPageSize(), page.getTotal(), list);
    }

    /**
     * 获取数据列表
     *
     * @param type       类型 1:上海黄金交易所
     * @param addTimeMin 最小操作时间
     * @param addTimeMax 最大操作时间
     * @return 列表
     */
    @Override
    @SaveCache(cacheType = SEARCH)
    public List<GoldPriceTrendBean> queryTrend(Integer type, LocalDateTime addTimeMin, LocalDateTime addTimeMax, Integer day) {
        List<GoldPriceTrendBean> dataList = new ArrayList<>();
        //boolean flag = day.intValue() == YEAR;
        //修正2018-9-4 365天条件筛选是查询24点的金价数据  其他的是12点的金价数据
        //修正2019-11-29 7天条件筛选24*7条数据，30天条件筛选6*30条数据，365天条件不变
        List<String> timeType = new ArrayList<>();
        String[] hours = {};
        if (day.intValue() == MONTH) {
            hours = new String[] {"00","04","08","12","16","20"};
        }
        if (day.intValue() == week) {
            hours = new String[] {"00","01","02","03","04","05","06","07","08","09","10","11",
                                  "12","13","14","15","16","17","18","19","20","21","22","23"};
        }
        if (day.intValue() == YEAR) {
            hours = new String[] {"00"};
        }
        timeType = Arrays.asList(hours);
        List<GoldPriceRecord> list;
        if (day.intValue() == YEAR) {
            list = goldPriceRecordMapper.queryTrend(
                    getParams()
                            .put("type", type)
                            .put("addTimeMin", addTimeMin)
                            .put("addTimeMax", addTimeMax)
                            //.put("timeType", flag ? "00" : "12")
                            .put("timeType", timeType.get(0))
                            .toMap());
        } else {
            list = goldPriceRecordMapper.queryTrendByTimeType(
                    getParams()
                            .put("type", type)
                            .put("addTimeMin", addTimeMin)
                            .put("addTimeMax", addTimeMax)
                            .put("timeType", timeType)
                            .toMap());
        }

//        Map<String, GoldPriceTrendBean> dataMap = new HashMap<>();
        for (GoldPriceRecord o : list) {
//            GoldPriceTrendBean objBean = dozerBeanMapper.map(o, GoldPriceTrendBean.class);
//            if (flag) {
//                objBean.setAddTimeString(UF.getFormatDateTime("yyyy-MM-dd 00:00:00", o.getAddTime()));
//            } else {
//                objBean.setAddTimeString(UF.getFormatDateTime("yyyy-MM-dd 12:00:00", o.getAddTime()));
//            }
//            objBean.setModifyTimeString(objBean.getAddTimeString());
//            dataMap.put(o.getAddTime().toLocalDate().toString(), objBean);
            GoldPriceTrendBean bean = new GoldPriceTrendBean();
            bean.setAddTimeString(UF.getFormatDateTime("yyyy-MM-dd HH:00:00",o.getAddTime()));
            bean.setModifyTimeString(bean.getAddTimeString());
            bean.setLatestpri(o.getLatestpri());
            bean.setActualpri(o.getActualpri());
            dataList.add(bean);
        }
//        LocalDate minDate = addTimeMin.toLocalDate();
//        LocalDate maxDate = addTimeMax.toLocalDate();
//        BigDecimal flagLatestpri = BigDecimal.ZERO;
//        BigDecimal flagActualpri = BigDecimal.ZERO;
//        while (true) {
//            GoldPriceTrendBean o = dataMap.get(minDate.toString());
//            if (o != null && flag) {
//                flagLatestpri = o.getLatestpri();
//                flagActualpri = o.getActualpri();
//            }
//
//            if (null == o) {
//                // 填充数据
//                o = new GoldPriceTrendBean();
//                if (flag) {
//                    o.setLatestpri(flagLatestpri);
//                    o.setActualpri(flagActualpri);
//                } else {
//                    o.setLatestpri(BigDecimal.ZERO);
//                    o.setActualpri(BigDecimal.ZERO);
//                }
//                if (flag) {
//                    o.setAddTimeString(minDate.toString() + " 00:00:00");
//                } else {
//                    o.setAddTimeString(minDate.toString() + " 12:00:00");
//                }
//                o.setModifyTimeString(o.getAddTimeString());
//            }
//            dataList.add(o);
//            minDate = minDate.plusDays(1);
//            if (minDate.compareTo(maxDate) >= 0) {
//                break;
//            }
//        }
        return dataList;
    }

    @Override
    public List<GoldPriceTrendBean> queryToday(Integer type) {
        List<GoldPriceTrendBean> dataList = new ArrayList<>();
        LocalDateTime addTimeMin = UF.getDate(UF.getFormatDateNow());
        LocalDateTime addTimeMax = addTimeMin.plusDays(1);
        DataTable<GoldPriceRecordBean> dataTable = query("add_time", "asc", 1, Integer.MAX_VALUE, type, addTimeMin, addTimeMax, null);
        if (null == dataTable || null == dataTable.getDataList() || dataTable.getDataList().isEmpty()) {
            return dataList;
        }
        Set<String> timeSet = new HashSet<>();
        int index = 0;
        for (GoldPriceRecordBean o : dataTable.getDataList()) {
            GoldPriceTrendBean objBean = dozerBeanMapper.map(o, GoldPriceTrendBean.class);
            String time = objBean.getAddTimeString();
			/*if(StringUtils.isNotBlank(time) && time.length() == "yyyy-MM-dd HH:mm:ss".length()) {
				// 十分钟一条数据
				time = time.substring(0, time.lastIndexOf(":") - 1);
			}
			if(!timeSet.add(time)) {
				continue;
			}*/
            if (StringUtils.isNotBlank(time) && time.length() == "yyyy-MM-dd HH:mm:ss".length()) {
                // 十分钟一条数据
                time = time.substring(0, time.lastIndexOf(":"));
            }
            if (!timeSet.add(time)) {
                continue;
            }
            if (index % 5 == 0) {
                dataList.add(objBean);
            }
            index++;
        }
        return dataList;
    }

    /**
     * 获取数据列表
     *
     * @param order      排序字段
     * @param sort       排序方式 desc或asc
     * @param type       类型 1:上海黄金交易所
     * @param addTimeMin 最小操作时间
     * @param addTimeMax 最大操作时间
     * @param keyword    关键字
     * @return 列表
     */
    private List<GoldPriceRecordBean> queryDetail(String order, String sort, Integer type,
                                                  LocalDateTime addTimeMin, LocalDateTime addTimeMax, String keyword) {
        List<GoldPriceRecordBean> dataList = new ArrayList<>();
        List<GoldPriceRecord> list = goldPriceRecordMapper.query(
                getParams(keyword, order, sort)
                        .put("type", type)
                        .put("addTimeMin", addTimeMin)
                        .put("addTimeMax", addTimeMax)
                        .toMap());
        for (GoldPriceRecord o : list) {
            GoldPriceRecordBean objBean = dozerBeanMapper.map(o, GoldPriceRecordBean.class);
            objBean.setTimeString(UF.getFormatDateTime(o.getTime()));
            objBean.setAddTimeString(UF.getFormatDateTime(o.getAddTime()));
            objBean.setModifyTimeString(UF.getFormatDateTime(o.getModifyTime()));
            dataList.add(objBean);
        }
        return dataList;
    }

    @Override
    public DataTable<GoldPriceRecordBean> queryPriceList(int pageSize,int pageNum,String startDate,String endDate) {
        if (pageSize < 0) {
            pageSize = config.getPageSize();
        }
        PageHelper.startPage(pageNum, pageSize);
        List<GoldPriceRecord> goldPriceRecordList = goldPriceRecordMapper.queryRecordList(getParams(null, null, null)
                .put("startDate", startDate)
                .put("endDate", endDate)
                .toMap());
        PageInfo<GoldPriceRecord> pageInfo = new PageInfo<>(goldPriceRecordList);
        List<GoldPriceRecordBean> dataList = new ArrayList<>();
        for (GoldPriceRecord goldPriceRecord : pageInfo.getList()) {
            GoldPriceRecordBean objBean = dozerBeanMapper.map(goldPriceRecord, GoldPriceRecordBean.class);
            objBean.setTimeString(UF.getFormatDateTime(goldPriceRecord.getTime()));
            objBean.setAddTimeString(UF.getFormatDateTime(goldPriceRecord.getAddTime()));
            objBean.setModifyTimeString(UF.getFormatDateTime(goldPriceRecord.getModifyTime()));
            dataList.add(objBean);
        }
        return new DataTable<>(pageInfo.getPageNum(), pageInfo.getPageSize(), pageInfo.getTotal(), dataList);
    }
}

